/*
 * 
 * 
 * 
 */
package com.hboxs.asl.service.impl;

import com.hboxs.asl.Constant;
import com.hboxs.asl.Principal;
import com.hboxs.asl.dao.CartDao;
import com.hboxs.asl.dao.CartItemDao;
import com.hboxs.asl.dao.MemberDao;
import com.hboxs.asl.dao.PromotionDao;
import com.hboxs.asl.entity.*;
import com.hboxs.asl.service.CartService;
import com.hboxs.asl.util.WebUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * Service - 购物车
 */
@Service("cartServiceImpl")
public class CartServiceImpl extends BaseServiceImpl<Cart, Long> implements CartService {

    @Resource(name = "cartDaoImpl")
    private CartDao cartDao;
    @Resource(name = "cartItemDaoImpl")
    private CartItemDao cartItemDao;
    @Resource(name = "memberDaoImpl")
    private MemberDao memberDao;
    @Resource(name = "promotionDaoImpl")
    private PromotionDao promotionDao;

    @Resource(name = "cartDaoImpl")
    public void setBaseDao(CartDao cartDao) {
        super.setBaseDao(cartDao);
    }

    public Cart getCurrent() {
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        if (requestAttributes != null) {
            HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
            Principal principal = (Principal) request.getSession().getAttribute(Member.PRINCIPAL_ATTRIBUTE_NAME);
            Member member = principal != null ? memberDao.find(principal.getId()) : null;
            if (member != null) {
                Cart cart = cartDao.findByMember(member);
                if (cart != null) {
//                    if (!cart.hasExpired()) {
                        if (!DateUtils.isSameDay(cart.getModifyDate(), new Date())) {
                            cart.setModifyDate(new Date());
                            cartDao.merge(cart);
                        }
                        return cart;
//                    } else {
//                        cartDao.remove(cart);
//                    }
                }
            } else {
                String id = WebUtils.getCookie(request, Cart.ID_COOKIE_NAME);
                String key = WebUtils.getCookie(request, Cart.KEY_COOKIE_NAME);
                if (StringUtils.isNotEmpty(id) && StringUtils.isNumeric(id) && StringUtils.isNotEmpty(key)) {
                    Cart cart = cartDao.find(Long.valueOf(id));
                    if (cart != null && cart.getMember() == null && StringUtils.equals(cart.getKey(), key)) {
//                        if (!cart.hasExpired()) {
                            if (!DateUtils.isSameDay(cart.getModifyDate(), new Date())) {
                                cart.setModifyDate(new Date());
                                cartDao.merge(cart);
                            }
                            return cart;
//                        } else {
//                            cartDao.remove(cart);
//                        }
                    }
                }
            }
        }
        return null;
    }

    public Cart getCurrentByToken() {
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        if (requestAttributes != null) {
            HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
            String token = request.getParameter("token");
            Member member = memberDao.findByToken2(token);
            if (member != null) {
                Cart cart = cartDao.findByMember(member);

                if (cart != null) {
//                    if (!cart.hasExpired()) {
                        if (!DateUtils.isSameDay(cart.getModifyDate(), new Date())) {
                            cart.setModifyDate(new Date());
                            cartDao.merge(cart);
                        }
                        return cart;
//                    } else {
//                        cartDao.remove(cart);
//                    }
                }
            } else {

                String id = request.getParameter("id");
                String key = request.getParameter("key");

                if (StringUtils.isNotEmpty(id) && StringUtils.isNumeric(id) && StringUtils.isNotEmpty(key)) {
                    Cart cart = cartDao.find(Long.valueOf(id));
                    if (cart != null && cart.getMember() == null && StringUtils.equals(cart.getKey(), key)) {
//                        if (!cart.hasExpired()) {
                            if (!DateUtils.isSameDay(cart.getModifyDate(), new Date())) {
                                cart.setModifyDate(new Date());
                                cartDao.merge(cart);
                            }
                            return cart;
//                        } else {
//                            cartDao.remove(cart);
//                        }
                    }
                }
            }
        }
        return null;
    }


    public void merge(Member member, Cart cart) {
        if (member != null && cart != null && cart.getMember() == null) {
            Cart memberCart = member.getCart();
            if (memberCart != null) {
                for (Iterator<CartItem> iterator = cart.getCartItems().iterator(); iterator.hasNext(); ) {
                    CartItem cartItem = iterator.next();
                    Product product = cartItem.getProduct();
                    if (memberCart.contains(product)) {
                        if (Cart.MAX_PRODUCT_COUNT != null && memberCart.getCartItems().size() > Cart.MAX_PRODUCT_COUNT) {
                            continue;
                        }
                        CartItem item = memberCart.getCartItem(product);
                        item.add(cartItem.getQuantity());
                        cartItemDao.merge(item);
                    } else {
                        if (Cart.MAX_PRODUCT_COUNT != null && memberCart.getCartItems().size() >= Cart.MAX_PRODUCT_COUNT) {
                            continue;
                        }
                        iterator.remove();
                        cartItem.setCart(memberCart);
                        memberCart.getCartItems().add(cartItem);
                        cartItemDao.merge(cartItem);
                    }
                }
                cartDao.remove(cart);
            } else {
                member.setCart(cart);
                cart.setMember(member);
                cartDao.merge(cart);
            }
        }
    }

    public void evictExpired() {
        cartDao.evictExpired();
    }

    @Override
    public void dealPromotion(Cart cart) {
        {
            if (cart == null) {
                return;
            }

            cart.getPromotions().clear();
            for (Promotion p : promotionDao.findUsingList()) {
                switch (p.getType()) {

                    // 包邮
                    case freeShipping:
                        if (p.getMinimumPrice().compareTo(cart.getSubtotalWithPromotion(p)) <= 0) {
                            cart.getPromotions().add(p);
                        } else {
                            cart.getPromotions().remove(p);
                        }
                        break;


                    // 满减
                    case subtract:
                        if (p.getMinimumPrice().compareTo(cart.getSubtotalWithPromotion(p)) <= 0) {
                            cart.getPromotions().add(p);
                        } else {
                            cart.getPromotions().remove(p);
                        }
                        break;

                }
            }

        }
    }

    @Override
    public void cancelSelected(Cart cart) {
        if (cart == null) {
            return;
        }
        Iterator<CartItem> it = cart.getCartItems().iterator();
        while (it.hasNext()) {
            CartItem ci = it.next();
            ci.setIsSelected(false);
            cartItemDao.merge(ci);
        }
    }

    @Override
    public Cart getCurrent(Member member) {
        Cart cart = getCurrent();
        if (cart == null) {
            cart = create(member);
        }
        return cart;
    }

    @Override
    public Cart getCurrentByToken(Member member) {
        Cart cart = getCurrentByToken();
        if (cart == null) {
            cart = create(member);
        }
        return cart;
    }

    private Cart create(Member member) {
        Cart cart = new Cart();
        cart.setKey(UUID.randomUUID().toString() + DigestUtils.md5Hex(RandomStringUtils.randomAlphabetic(30)));
        cart.setMember(member);
        save(cart);
        return cart;
    }

    @Override
    public void selectedAll(Cart cart) {

        //取消全选
        boolean flag = false;
        int i = 0;
        Set<CartItem> cartItems = cart.getCartItems();
        if (cartItems.size() != 0) {
            for (CartItem ci : cartItems) {
                if (ci.getIsSelected()) {
                    i++;
                    flag = true;
                }
            }
            if (i == 0) {
                flag = true;
            }
            if (i != 0 && i == cartItems.size()) {
                flag = false;
            }
            Iterator<CartItem> it = cartItems.iterator();
            while (it.hasNext()) {
                CartItem ci = it.next();
                ci.setIsSelected(flag);
                cartItemDao.merge(ci);
            }
        }
    }

    @Override
    public Long getTotalNumberOfGoodsInCart(Cart cart) {
        return cartDao.getTotalNumberOfGoodsInCart(cart);
    }

    @Override
    public List<Map<String, Object>> splitCart(Cart cart) {

        // 分离过程键值对
        Map<Long, Map<String, Object>> data = new HashMap<>();

        // 分离结果
        List<Map<String, Object>> result = new ArrayList<>();

        Set<CartItem> cartItems = cart.getCartItems();
        if(cartItems.size() > 0) {
            for (CartItem ci : cartItems) {

                Map<String, Object> merchantCartMap = null;
                List<Map<String, Object>> cartItemDataList = null;
                Product p = ci.getProduct();
                Long mId = 0l;
                if (p.getMerchant() != null) mId = p.getMerchant().getId();


                if (!data.containsKey(mId)) {

                    merchantCartMap = new HashMap<>();
                    data.put(mId, merchantCartMap);

                    cartItemDataList = new ArrayList<>();
                    merchantCartMap.put("cartItems", cartItemDataList);

                    if(mId!=0){
                        merchantCartMap.put("id", p.getMerchant().getId());
                        merchantCartMap.put("name", p.getMerchant().getName());
                        merchantCartMap.put("logo", p.getMerchant().getLogo());
                    }else{
                        merchantCartMap.put("id", "0");
                        merchantCartMap.put("name", Constant.ADMIN_MERCHANT_NAME);
                        merchantCartMap.put("logo", Constant.APP_LOGO);
                    }

                    result.add(merchantCartMap);

                } else {
                    merchantCartMap = data.get(mId);
                    cartItemDataList = (List<Map<String, Object>>) merchantCartMap.get("cartItems");
                }

                Map<String, Object> cartItemMap = new HashedMap();

                cartItemMap.put("pId", p.getId());
                cartItemMap.put("name", p.getName());
                cartItemMap.put("price", p.getPrice());
                cartItemMap.put("promotionPrice", p.getPromotionPrice());
                cartItemMap.put("specValNames", p.getSpecValNames());
                cartItemMap.put("image", p.getImage());
                cartItemMap.put("unit", p.getUnit());
                cartItemMap.put("subtotal", ci.getSubtotal());
                cartItemMap.put("quantity", ci.getQuantity());
                cartItemMap.put("id", ci.getId());
                cartItemMap.put("isSelected", ci.getIsSelected());
                cartItemMap.put("weight", ci.getWeight());
                cartItemMap.put("dealPrice", ci.getDealPrice());
                cartItemMap.put("merchantId", p.getMerchant());
                cartItemMap.put("point", p.getPoint());
                cartItemMap.put("mPoint", p.getmPoint());
                ((List<Map<String, Object>>) merchantCartMap.get("cartItems")).add(cartItemMap);

            }
        }

        return result;
    }
}
